import {
  Injectable,
  PipeTransform,
  ArgumentMetadata,
  BadRequestException
} from '@nestjs/common'
import { validate } from 'class-validator'
import { plainToClass } from 'class-transformer'

@Injectable()
export class ValidationPipe implements PipeTransform<any> {
  async transform(
    value: unknown,
    { metatype }: ArgumentMetadata
  ): Promise<any> {
    if (!metatype || !this.toValidate(metatype)) {
      return value
    }

    const object = plainToClass(metatype, value, { ignoreDecorators: true })
    const errors = await validate(object)

    if (errors.length > 0) {
      const message = errors.reduce((total, item) => {
        const itemMsg = Object.values(item.constraints)
        total.push(...itemMsg)
        return total
      }, [])

      throw new BadRequestException(message)
    }
    return value
  }

  private toValidate(metatype: unknown): boolean {
    const types: unknown[] = [String, Boolean, Number, Array, Object]
    return !types.includes(metatype)
  }
}
